using System.Collections;
using System.Web;

namespace Avanzis.QueryObjects
{
    public class ManagedWebSessionContext : ICurrentSessionContext
    {
        private const string SessionFactoryMapKey = "QueryObjects.Context.ManagedWebSessionContext.SessionFactoryMapKey";

        private readonly SessionFactory factory;

        public ManagedWebSessionContext(SessionFactory factory)
        {
            this.factory = factory;
        }

        public Session CurrentSession()
        {
            Session currentSession = GetExistingSession(HttpContext.Current, factory);
            if (currentSession == null)
            {
                throw new QueryObjectsException("No session bound to the current HttpContext");
            }
            return currentSession;
        }

        #region Static API

        public static void Bind(HttpContext context, Session session)
        {
            GetSessionMap(context, true)[session.Factory] = session;
        }

        public static bool HasBind(HttpContext context, SessionFactory factory)
        {
            return GetExistingSession(context, factory) != null;
        }

        public static Session Unbind(HttpContext context, SessionFactory factory)
        {
            Session result = null;

            IDictionary sessionMap = GetSessionMap(context, false);

            if (sessionMap != null)
            {
                result = sessionMap[factory] as Session;
                sessionMap.Remove(factory);
            }
            return result;
        }

        #endregion

        private static Session GetExistingSession(HttpContext context, SessionFactory factory)
        {
            IDictionary sessionMap = GetSessionMap(context, false);
            if (sessionMap == null)
            {
                return null;
            }

            return sessionMap[factory] as Session;
        }

        private static IDictionary GetSessionMap(HttpContext context, bool create)
        {
            IDictionary map = context.Items[SessionFactoryMapKey] as IDictionary;
            if (map == null && create)
            {
                map = new Hashtable();
                context.Items[SessionFactoryMapKey] = map;
            }
            return map;
        }
    }
}
